home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / CUGUK / COMMS / C011.ZIP / USQ.C < prev   
Text File  |  1990-01-19  |  7KB  |  284 lines

  1. /********************************************************************
  2.  * C Users Group (U.K) C Source Code Library File CUGLIB.011        *
  3.  * Inquiries to: M. Houston, 36 Whetstone Clo. Farquhar Rd.         *
  4.  * Edgbaston, Birmingham B15 2QN ENGLAND                *
  5.  ********************************************************************
  6.  * File name: usq.c
  7.  * Program name: usq
  8.  * Source of file: The Public Domain Software Library.
  9.  * Purpose: file un-squeeze program
  10.  * Changes: <who what when & why major changes have been made>      
  11.  ********************************************************************/
  12.  
  13. /*% cc -O -n % -o usq
  14. */
  15. char Version[] = {"usq revised 8-13-83"};                              /* 1.7 */
  16.  
  17. /*
  18.  *
  19.  *    08/13/83  C86 Version by Wayne Fruhwald
  20.  *    Converted to work with Computer Innovation's C86 c compiler under MSDOS.
  21.  *
  22.  */
  23.  
  24. #include <stdio.h>
  25. /*  #include <signal.h>  */                           /* 1.7 */
  26. /*  #include <ctype.h>     */                           /* 1.7 */
  27. #define TRUE 1
  28. #define FALSE 0
  29. #define ERROR (-1)
  30. #define PATHLEN 312    /* Number of characters allowed in pathname */
  31. #define OK 0
  32.  
  33. #define RECOGNIZE 0xFF76    /* unlikely pattern */
  34. #define DLE 0x90        /* repeat byte flag */
  35. #define SPEOF 256        /* special endfile token */
  36. #define NUMVALS 257        /* 256 data values plus SPEOF*/
  37. #define LARGE 30000
  38.  
  39. struct _sqleaf {        /* Decoding tree */
  40.     int _children[2];    /* left, right */
  41. };
  42. struct _sqleaf Dnode[NUMVALS - 1];
  43.  
  44.  
  45. int Bpos;        /* last bit position read */
  46. int Curin;        /* last byte value read */
  47. int Repct;        /* Number of times to retirn value */
  48. int Value;        /* current byte value or EOF */
  49.  
  50. int MakeLCPathname=TRUE;    /* translate pathname to lc if all caps */
  51. int Nlmode=FALSE;        /* zap cr's if true */
  52.  
  53. main(argc, argv)
  54. char *argv[];
  55. {
  56.     register char *cp;
  57.     register npats=0;
  58.     char **patts;
  59.     int n, errorstat;
  60.  
  61.     errorstat=0;
  62.     if(argc<2)
  63.         goto usage;
  64.     while (--argc) {
  65.         cp = *++argv;
  66.         if(*cp == '-') {
  67.             while( *++cp) {
  68.                 switch(*cp) {
  69.                 case 'n':
  70.                     Nlmode=TRUE; break;
  71.                 case 'u':
  72.                     MakeLCPathname=FALSE; break;
  73.                 default:
  74.                     goto usage;
  75.                 }
  76.             }
  77.         }
  78.         else if( !npats && argc>0) {
  79.             if(argv[0][0]) {
  80.                 npats=argc;
  81.                 patts=argv;
  82.             }
  83.         }
  84.     }
  85.     if(npats < 1) {
  86. usage:
  87.         fprintf(stderr,"Usage: usq [-nu] file ...\n");
  88.         fprintf(stderr,"\t-n Nlmode: remove carriage returns\n");
  89.         fprintf(stderr,"\tx-u preserve Uppercase pathnames\n");
  90.         exit(1);
  91.     }
  92.     for(n=0; n<npats; ++n)
  93.         errorstat |= squeeze(patts[n]);
  94.     exit(errorstat != 0);
  95. }
  96.  
  97. /*
  98.     The following code is primarily from typesq.c and utr.c.  Typesq
  99. is a modification of USQ by Dick Greenlaw.  Those modifications (usq
  100. to typesq) were made by Bob Mathias, I am responsible for the butchery
  101. done to make it work with cat.
  102.  
  103. */
  104.  
  105. FILE *in, *out;
  106. squeeze(fname)
  107. char *fname;
  108. {
  109.     register i, c;
  110.     register char *p;
  111.     register int numnodes;            /* size of decoding tree */
  112.     register unsigned crc;
  113.     unsigned filecrc;
  114.     char origname[PATHLEN];     /* Original file name without drive */
  115.  
  116.     init_cr(); init_huff(); crc=0;
  117.  
  118.     if((in=fopen( fname, "rb"))==NULL) {                           /* 1.7 */
  119.         fprintf(stderr, "usq: can't open %s\n", fname);
  120.         return ERROR;
  121.     }
  122.     if(portgetw(in) != RECOGNIZE) { /* Process header */
  123.         fprintf(stderr, "usq: %s is not a SQueezed file\n", fname);
  124.         return ERROR;
  125.     }
  126.     filecrc=portgetw(in);            /* checksum */
  127.     p = origname;                /* Get original file name */
  128.     do {                    /* send it to array */
  129.         *p = getc(in);
  130.     } while(*p++ != '\0');
  131.  
  132.     numnodes = portgetw(in);
  133.     if(numnodes < 0 || numnodes >= NUMVALS) {
  134.         fprintf(stderr, "usq: %s has invalid decode tree\n", fname);
  135.         fclose(in);
  136.         return ERROR;
  137.     }
  138.     /* Initialize for possible empty tree (SPEOF only) */
  139.     Dnode[0]._children[0] = -(SPEOF + 1);
  140.     Dnode[0]._children[1] = -(SPEOF + 1);
  141.  
  142.     for(i = 0; i < numnodes; ++i) { /* Get decoding tree from file */
  143.         Dnode[i]._children[0] = portgetw(in);
  144.         Dnode[i]._children[1] = portgetw(in);
  145.     }
  146.     /* Get translated output bytes and write file */
  147.     if(MakeLCPathname && !IsAnyLower(origname))
  148.         uncaps(origname);
  149.     fprintf(stderr, "usq: %s -> %s\n",fname,origname);
  150.     if((out=fopen(origname, "wb"))==NULL) {                        /* 1.7 */
  151.         fprintf("usq: can't create %s\n", origname);
  152.     }
  153.     while ((c = getcr()) != EOF) {
  154.         crc += c;
  155.         if ( c == '\r' && Nlmode)
  156.             continue;
  157.         putc(c, out);
  158.     }
  159.     fclose(in);
  160.     fflush(out);
  161.     fclose(out);
  162.     if( crc != filecrc ) {
  163.         fprintf(stderr, "usq: bad checksum in %s\n", fname);
  164.         return ERROR;
  165.     }
  166.     return OK;
  167. }
  168. /*** from utr.c - */
  169. /* initialize decoding functions */
  170.  
  171. init_cr()
  172. {
  173.     Repct = 0;
  174. }
  175.  
  176. init_huff()
  177. {
  178.     Bpos = 99;    /* force initial read */
  179. }
  180.  
  181. /* Get bytes with decoding - this decodes repetition,
  182.  * calls getuhuff to decode file stream into byte
  183.  * level code with only repetition encoding.
  184.  *
  185.  * The code is simple passing through of bytes except
  186.  * that DLE is encoded as DLE-zero and other values
  187.  * repeated more than twice are encoded as value-DLE-count.
  188.  */
  189.  
  190. int
  191. getcr()
  192. {
  193.     register c;
  194.  
  195.     if(Repct > 0) {
  196.         /* Expanding a repeated char */
  197.         --Repct;
  198.         return Value;
  199.     } else {
  200.         /* Nothing unusual */
  201.         if((c = getuhuff()) != DLE) {
  202.             /* It's not the special delimiter */
  203.             Value = c;
  204.             if(Value == EOF)
  205.                 Repct = LARGE;
  206.             return Value;
  207.         } else {
  208.             /* Special token */
  209.             if((Repct = getuhuff()) == 0)
  210.                 /* DLE, zero represents DLE */
  211.                 return DLE;
  212.             else {
  213.                 /* Begin expanding repetition */
  214.                 Repct -= 2;    /* 2nd time */
  215.                 return Value;
  216.             }
  217.         }
  218.     }
  219. }
  220. /* Decode file stream into a byte level code with only
  221.  * repetition encoding remaining.
  222.  */
  223.  
  224. int
  225. getuhuff()
  226. {
  227.     register i;
  228.     register bitval;
  229.  
  230.     /* Follow bit stream in tree to a leaf*/
  231.     i = 0;    /* Start at root of tree */
  232.     do {
  233.         if(++Bpos > 7) {
  234.             if((Curin = getc(in)) == ERROR)
  235.                 return ERROR;
  236.             Bpos = 0;
  237.             /* move a level deeper in tree */
  238.             i = Dnode[i]._children[1 & Curin];
  239.         } else
  240.             i = Dnode[i]._children[1 & (Curin >>= 1)];
  241.     } while(i >= 0);
  242.  
  243.     /* Decode fake node index to original data value */
  244.     i = -(i + 1);
  245.     /* Decode special endfile token to normal EOF */
  246.     i = (i == SPEOF) ? EOF : i;
  247.     return i;
  248. }
  249. /*
  250.  * Machine independent getw which always gets bytes in the same order
  251.  *  as the CP/M version of SQ wrote them
  252.  */
  253. portgetw(f)
  254. FILE *f;
  255. {
  256.     register c;
  257.  
  258.     c = getc(f)&0377;
  259.     return c + (getc(f)<<8);
  260. }
  261.  
  262.  
  263. /* make string s lower case */
  264. uncaps(s)
  265. register char *s;
  266. {
  267.     for( ; *s; ++s)
  268.         if(isupper(*s))
  269.             *s = tolower(*s);
  270. }
  271.  
  272.  
  273. /*
  274.  * IsAnyLower returns TRUE if string s has lower case letters.
  275.  */
  276. IsAnyLower(s)
  277. register char *s;
  278. {
  279.     for( ; *s; ++s)
  280.         if (islower(*s))
  281.             return TRUE;
  282.     return FALSE;
  283. }
  284.